import numpy as np
import pandas as pd

from pyecharts.charts import Tree, Bar
from pyecharts.commons.utils import JsCode
from pyecharts.options import LabelOpts, TooltipOpts, AnimationOpts, InitOpts, AxisOpts, DataZoomOpts

RI = (0, 0, 0.58, 0.9, 1.12, 1.24, 1.32, 1.41, 1.45, 1.49)


def calc_weights(df: pd.DataFrame):
    input_matrix = df.values
    n = input_matrix.shape[0]

    eigenvalues, eigenvectors = np.linalg.eig(input_matrix)

    max_idx = np.argmax(eigenvalues)
    max_eigen = eigenvalues[max_idx].real
    eigen = eigenvectors[:, max_idx].real
    eigen = eigen / eigen.sum()

    if n > 9:
        raise Exception('无法判断一致性')
    else:
        return {'CR': (max_eigen - n) / (n - 1) / RI[n],
                'weight': eigen}


def point_to_float(point):
    point_map = {'1/9': 1 / 9,
                 '1/7': 1 / 7,
                 '1/5': 1 / 5,
                 '1/3': 1 / 3}
    res = point_map.get(point)
    if res is None:
        return float(point)
    return res


def map_to_matrix(v):
    df = pd.DataFrame()
    for pair in v:
        df.loc[pair[0], pair[1]] = pair[2]
        df.loc[pair[1], pair[0]] = 1 / pair[2]
    for c in df.columns:
        df.loc[c, c] = 1
    return df.sort_index()


def get_result_bar(alternative_names, criteria_results):
    b = (
        Bar(
            InitOpts(
                width="1600px", height="500px",
                animation_opts=AnimationOpts(animation_duration=550, animation_duration_update=750)
            )
        )
        .add_dataset(
            source=[["criteria"] + alternative_names] + criteria_results,
        )
    )
    for an in alternative_names:
        b = b.add_yaxis(
            series_name=an,
            y_axis=[]
        )
    b = (
        b
        .set_global_opts(
            xaxis_opts=AxisOpts(type_="category"),
            datazoom_opts=DataZoomOpts(range_start=0, range_end=25)
        )
        .set_series_opts(
            label_opts=LabelOpts(
                is_show=False
            )
        )
        .render_embed()
    )

    return b


def get_model_structure(model_entry, width="1000px", height="800px"):
    tree_init_options = InitOpts(
        width=width, height=height,
        animation_opts=AnimationOpts(animation_duration=550, animation_duration_update=750)
    )
    tree_add_options = dict(
        pos_top="1%",
        pos_bottom="1%",
        pos_left="7%",
        pos_right="20%",
        collapse_interval=3,
        symbol_size=7,
        initial_tree_depth=-1,
        label_opts=LabelOpts(
            position='top',
            vertical_align='middle',
            horizontal_align='right',
            font_size=9
        ),
        leaves_label_opts=LabelOpts(
            position='right',
            vertical_align='middle',
            horizontal_align='left'
        ),
        # tooltip_opts=TooltipOpts(formatter='{c}: {@desc}'),
    )
    context = {"model_name": model_entry.name,
               "model_desc": model_entry.desc,
               "model_tree": Tree(tree_init_options).add("", [model_entry.context], **tree_add_options).render_embed(),
               }

    return context


